const fs = require('fs');
const path = require('path');
const Parser = require('web-tree-sitter');

async function initParser() {
  await Parser.init();
  const C = await Parser.Language.load(path.join(__dirname, 'tree-sitter-c.wasm'));
  const parser = new Parser();
  parser.setLanguage(C);
  return parser;
}

// 解析C头文件，提取函数声明、结构体定义和枚举定义
async function parseHeaderFile(parser, filePath) {
  try {
    if (!fs.existsSync(filePath)) {
      console.error(`文件不存在: ${filePath}`);
      return { functions: [], structs: [], enums: [] };
    }

    const fileContent = fs.readFileSync(filePath, 'utf8');
    const tree = parser.parse(fileContent);
    const root = tree.rootNode;

    const functions = [];
    const structs = [];
    const enums = [];
    const typedefs = [];

    // 遍历语法树查找函数声明、结构体定义和枚举定义
    traverseTree(root, {
      function_declaration: (node) => {
        const funcName = node.childForFieldName('declarator')?.childForFieldName('declarator')?.text;
        if (funcName) {
          const returnType = node.childForFieldName('type')?.text || 'void';
          const params = [];
          
          const paramListNode = node.childForFieldName('declarator')?.childForFieldName('parameters');
          if (paramListNode) {
            for (let i = 0; i < paramListNode.namedChildCount; i++) {
              const paramNode = paramListNode.namedChild(i);
              const paramType = paramNode.childForFieldName('type')?.text || '';
              const paramName = paramNode.childForFieldName('declarator')?.text || '';
              params.push({ type: paramType, name: paramName });
            }
          }
          
          functions.push({ name: funcName, returnType, params });
        }
      },
      struct_specifier: (node) => {
        const structName = node.childForFieldName('name')?.text;
        if (structName) {
          const fields = [];
          const bodyNode = node.childForFieldName('body');
          
          if (bodyNode) {
            for (let i = 0; i < bodyNode.namedChildCount; i++) {
              const fieldNode = bodyNode.namedChild(i);
              if (fieldNode.type === 'field_declaration') {
                const fieldType = fieldNode.childForFieldName('type')?.text || '';
                const declaratorNode = fieldNode.childForFieldName('declarator');
                if (declaratorNode) {
                  const fieldName = declaratorNode.text;
                  fields.push({ type: fieldType, name: fieldName });
                }
              }
            }
          }
          
          structs.push({ name: structName, fields });
        }
      },
      enum_specifier: (node) => {
        const enumName = node.childForFieldName('name')?.text;
        if (enumName) {
          const values = [];
          const bodyNode = node.childForFieldName('body');
          
          if (bodyNode) {
            for (let i = 0; i < bodyNode.namedChildCount; i++) {
              const enumValueNode = bodyNode.namedChild(i);
              if (enumValueNode.type === 'enumerator') {
                const valueName = enumValueNode.childForFieldName('name')?.text;
                const valueNode = enumValueNode.childForFieldName('value');
                const value = valueNode ? valueNode.text : null;
                values.push({ name: valueName, value });
              }
            }
          }
          
          enums.push({ name: enumName, values });
        }
      },
      typedef_declaration: (node) => {
        const typeNode = node.childForFieldName('type');
        const declaratorNode = node.childForFieldName('declarator');
        
        if (typeNode && declaratorNode) {
          typedefs.push({
            originalType: typeNode.text,
            newType: declaratorNode.text
          });
        }
      }
    });

    return { functions, structs, enums, typedefs };
  } catch (error) {
    console.error(`解析文件 ${filePath} 时出错:`, error);
    return { functions: [], structs: [], enums: [], typedefs: [] };
  }
}

// 遍历语法树的辅助函数
function traverseTree(node, handlers) {
  if (handlers[node.type]) {
    handlers[node.type](node);
  }
  
  for (let i = 0; i < node.childCount; i++) {
    traverseTree(node.child(i), handlers);
  }
}

// 解析C源文件，提取函数实现
async function parseSourceFile(parser, filePath) {
  try {
    if (!fs.existsSync(filePath)) {
      console.error(`文件不存在: ${filePath}`);
      return { functionImplementations: [] };
    }

    const fileContent = fs.readFileSync(filePath, 'utf8');
    const tree = parser.parse(fileContent);
    const root = tree.rootNode;

    const functionImplementations = [];

    // 遍历语法树查找函数实现
    traverseTree(root, {
      function_definition: (node) => {
        const funcName = node.childForFieldName('declarator')?.childForFieldName('declarator')?.text;
        if (funcName) {
          const returnType = node.childForFieldName('type')?.text || 'void';
          const params = [];
          
          const paramListNode = node.childForFieldName('declarator')?.childForFieldName('parameters');
          if (paramListNode) {
            for (let i = 0; i < paramListNode.namedChildCount; i++) {
              const paramNode = paramListNode.namedChild(i);
              const paramType = paramNode.childForFieldName('type')?.text || '';
              const paramName = paramNode.childForFieldName('declarator')?.text || '';
              params.push({ type: paramType, name: paramName });
            }
          }
          
          functionImplementations.push({ name: funcName, returnType, params });
        }
      }
    });

    return { functionImplementations };
  } catch (error) {
    console.error(`解析文件 ${filePath} 时出错:`, error);
    return { functionImplementations: [] };
  }
}

// 解析C++测试文件，提取需要mock的函数
async function parseTestFile(parser, filePath) {
  try {
    if (!fs.existsSync(filePath)) {
      console.error(`文件不存在: ${filePath}`);
      return { mockedFunctions: [] };
    }

    const fileContent = fs.readFileSync(filePath, 'utf8');
    // 使用正则表达式查找extern "C" 块中的函数声明
    const externCBlocks = fileContent.match(/extern\s+"C"\s*\{[^\}]*\}/g) || [];
    
    const mockedFunctions = [];
    
    for (const block of externCBlocks) {
      // 提取函数声明
      const functionDeclarations = block.match(/void\s+([A-Za-z0-9_]+)\s*\([^\)]*\)\s*\{/g) || [];
      
      for (const declaration of functionDeclarations) {
        // 提取函数名
        const funcNameMatch = declaration.match(/void\s+([A-Za-z0-9_]+)/);
        if (funcNameMatch && funcNameMatch[1]) {
          const funcName = funcNameMatch[1];
          
          // 提取参数
          const paramsMatch = declaration.match(/\(([^\)]*)\)/);
          const paramsStr = paramsMatch ? paramsMatch[1] : '';
          const paramsList = paramsStr.split(',').map(param => param.trim()).filter(param => param);
          
          const params = paramsList.map(param => {
            const parts = param.split(/\s+/);
            const paramName = parts.pop();
            const paramType = parts.join(' ');
            return { type: paramType, name: paramName };
          });
          
          mockedFunctions.push({ name: funcName, params });
        }
      }
    }

    return { mockedFunctions };
  } catch (error) {
    console.error(`解析文件 ${filePath} 时出错:`, error);
    return { mockedFunctions: [] };
  }
}

// 从测试文件中提取枚举值
function extractEnumValuesFromTestFile(testFilePath) {
  try {
    const fileContent = fs.readFileSync(testFilePath, 'utf8');
    
    // 提取tArbitrationState枚举值
    const arbitrationStateValues = [];
    const arbitrationMatches = fileContent.match(/ARBITRATION_[A-Z_]+/g) || [];
    arbitrationMatches.forEach(match => {
      if (!arbitrationStateValues.includes(match)) {
        arbitrationStateValues.push(match);
      }
    });
    
    // 提取tQualityFactor枚举值
    const qualityFactorValues = [];
    const qualityMatches = fileContent.match(/QUALITY_FACTOR_[A-Z_]+/g) || [];
    qualityMatches.forEach(match => {
      if (!qualityFactorValues.includes(match)) {
        qualityFactorValues.push(match);
      }
    });
    
    return {
      tArbitrationState: arbitrationStateValues,
      tQualityFactor: qualityFactorValues
    };
  } catch (error) {
    console.error(`从测试文件提取枚举值时出错:`, error);
    return { tArbitrationState: [], tQualityFactor: [] };
  }
}

// 生成枚举定义文件
function generateEnumsHeader(enumValues, outputPath) {
  const content = `#ifndef TEST_ENUMS_H
#define TEST_ENUMS_H

// 自动生成的枚举定义，用于测试

// 仲裁状态枚举
typedef enum {
${enumValues.tArbitrationState.map((value, index) => `  ${value} = ${index}`).join(',\n')}
} tArbitrationState;

// 质量因子枚举
typedef enum {
${enumValues.tQualityFactor.map((value, index) => `  ${value} = ${index}`).join(',\n')}
} tQualityFactor;

// 基本类型定义
typedef float Float32;
typedef float mmPerSec;
typedef unsigned char uint8;
typedef unsigned char Boolean;

#endif /* TEST_ENUMS_H */
`;

  fs.writeFileSync(outputPath, content);
  console.log(`生成枚举定义文件: ${outputPath}`);
}

// 生成结构体定义
function generateStructDefinitions(structs) {
  return structs.map(struct => {
    return `struct ${struct.name} {
${struct.fields.map(field => `  ${field.type} ${field.name};`).join('\n')}
};`;
  }).join('\n\n');
}

// 生成mock实现文件
function generateMockImplementation(functions, structs, outputPath) {
  const structDefinitions = generateStructDefinitions(structs);
  
  const mockClassMethods = functions.map(func => {
    const paramTypes = func.params.map(param => param.type).join(', ');
    return `  MOCK_METHOD${func.params.length}(${func.name}, ${func.returnType}(${paramTypes}));`;
  }).join('\n');
  
  const mockImplementations = functions.map(func => {
    const paramDeclarations = func.params.map(param => `${param.type} ${param.name}`).join(', ');
    const paramNames = func.params.map(param => param.name).join(', ');
    
    return `${func.returnType} ${func.name}(${paramDeclarations}) {
  if (g_mockObject) {
    g_mockObject->${func.name}(${paramNames});
  }
  
  // 默认实现
}`;
  }).join('\n\n');
  
  const content = `#include <gtest/gtest.h>
#include "gmock/gmock.h"
#include "../include/test_enums.h"

// 自动生成的结构体定义
${structDefinitions}

// 全局变量声明
extern "C" {
${structs.map(struct => `  struct ${struct.name} var_${struct.name} = {0};`).join('\n')}
}

// Mock类定义
class MockObject {
public:
${mockClassMethods}
};

// 创建全局mock对象
MockObject* g_mockObject = nullptr;

// 实际的mock实现
extern "C" {
${mockImplementations}
}

// 测试设置和清理函数
extern "C" {
  void setupMock() {
    g_mockObject = new MockObject();
  }
  
  void teardownMock() {
    delete g_mockObject;
    g_mockObject = nullptr;
  }
}
`;

  fs.writeFileSync(outputPath, content);
  console.log(`生成mock实现文件: ${outputPath}`);
}

// 生成mock头文件
function generateMockHeader(outputPath) {
  const content = `#ifndef MOCKS_H
#define MOCKS_H

#include "../include/test_enums.h"

// 设置和清理mock对象的函数声明
#ifdef __cplusplus
extern "C" {
#endif

void setupMock();
void teardownMock();

#ifdef __cplusplus
}
#endif

#endif /* MOCKS_H */
`;

  fs.writeFileSync(outputPath, content);
  console.log(`生成mock头文件: ${outputPath}`);
}

// 更新测试文件
function updateTestFile(testFilePath) {
  try {
    const fileContent = fs.readFileSync(testFilePath, 'utf8');
    
    // 更新SetUp和TearDown方法
    const updatedContent = fileContent.replace(
      /void SetUp\(\) override \{[^\}]*\}/,
      'void SetUp() override {\n        // 初始化mock对象\n        setupMock();\n    }'
    ).replace(
      /void TearDown\(\) override \{[^\}]*\}/,
      'void TearDown() override {\n        // 清理mock对象\n        teardownMock();\n    }'
    );
    
    // 更新头文件包含
    const updatedWithIncludes = updatedContent.replace(
      /#include "ActiveReturn_Ear\/Source\/AR_CD_ActvnMgr.h"/,
      '#include "../include/test_enums.h"\n#include "../mocks/mocks.h"'
    );
    
    // 移除原始的mock实现
    const finalContent = updatedWithIncludes.replace(
      /\/\/ Mock for [\s\S]*?\/\/ Mock for [\s\S]*?\/\/ Mock for [\s\S]*?\}\n\}/,
      '// 使用生成的mock实现'
    );
    
    fs.writeFileSync(testFilePath, finalContent);
    console.log(`更新测试文件: ${testFilePath}`);
  } catch (error) {
    console.error(`更新测试文件时出错:`, error);
  }
}

// 更新CMakeLists.txt
function updateCMakeLists(cmakeFilePath, mockFilePath) {
  try {
    const fileContent = fs.readFileSync(cmakeFilePath, 'utf8');
    const relativeMockPath = path.relative(path.dirname(cmakeFilePath), mockFilePath).replace(/\\/g, '\\\\');
    
    const updatedContent = fileContent.replace(
      /set\(SOURCES[^\)]*\)/,
      `set(SOURCES\n    src\\test.cpp\n    ${relativeMockPath}\n)`
    );
    
    fs.writeFileSync(cmakeFilePath, updatedContent);
    console.log(`更新CMakeLists.txt: ${cmakeFilePath}`);
  } catch (error) {
    console.error(`更新CMakeLists.txt时出错:`, error);
  }
}

async function generateMocks() {
  try {
    // 项目路径配置
    const projectRoot = path.resolve(__dirname, '..');
    const cProjectPath = path.join(projectRoot, 'c_project');
    const testPath = path.join(cProjectPath, 'tests', 'ActiveReturn_Ear_Source_AR_CD_ActvnMgr_AR_CD_ActvnMgr_test');
    const mockDir = path.join(testPath, 'mocks');
    const includeDir = path.join(testPath, 'include');
    
    // 确保目录存在
    if (!fs.existsSync(mockDir)) {
      fs.mkdirSync(mockDir, { recursive: true });
    }
    if (!fs.existsSync(includeDir)) {
      fs.mkdirSync(includeDir, { recursive: true });
    }
    
    // 初始化解析器
    const parser = await initParser();
    
    // 解析头文件
    const headerFilePath = path.join(cProjectPath, 'ActiveReturn_Ear', 'Source', 'AR_CD_ActvnMgr.h');
    const { functions, structs, enums, typedefs } = await parseHeaderFile(parser, headerFilePath);
    
    // 解析源文件
    const sourceFilePath = path.join(cProjectPath, 'ActiveReturn_Ear', 'Source', 'AR_CD_ActvnMgr.c');
    const { functionImplementations } = await parseSourceFile(parser, sourceFilePath);
    
    // 解析测试文件
    const testFilePath = path.join(testPath, 'src', 'test.cpp');
    const { mockedFunctions } = await parseTestFile(parser, testFilePath);
    
    // 提取枚举值
    const enumValues = extractEnumValuesFromTestFile(testFilePath);
    
    // 生成枚举定义文件
    const enumsHeaderPath = path.join(includeDir, 'test_enums.h');
    generateEnumsHeader(enumValues, enumsHeaderPath);
    
    // 生成mock实现文件
    const mockImplPath = path.join(mockDir, 'mocks.cpp');
    generateMockImplementation(functions, structs, mockImplPath);
    
    // 生成mock头文件
    const mockHeaderPath = path.join(mockDir, 'mocks.h');
    generateMockHeader(mockHeaderPath);
    
    // 更新测试文件
    updateTestFile(testFilePath);
    
    // 更新CMakeLists.txt
    const cmakeFilePath = path.join(testPath, 'CMakeLists.txt');
    updateCMakeLists(cmakeFilePath, mockImplPath);
    
    console.log('所有mock文件生成完成！');
    
  } catch (error) {
    console.error('生成mock文件时出错:', error);
  }
}

// 下载tree-sitter-c.wasm文件的函数
async function downloadTreeSitterWasm() {
  const wasmPath = path.join(__dirname, 'tree-sitter-c.wasm');
  
  // 如果文件已存在，则跳过下载
  if (fs.existsSync(wasmPath)) {
    console.log('tree-sitter-c.wasm 文件已存在，跳过下载');
    return;
  }
  
  console.log('正在下载 tree-sitter-c.wasm...');
  
  try {
    const https = require('https');
    const file = fs.createWriteStream(wasmPath);
    
    const url = 'https://github.com/tree-sitter/tree-sitter-c/raw/master/tree-sitter-c.wasm';
    
    https.get(url, (response) => {
      if (response.statusCode !== 200) {
        throw new Error(`下载失败，状态码: ${response.statusCode}`);
      }
      
      response.pipe(file);
      
      file.on('finish', () => {
        file.close();
        console.log('tree-sitter-c.wasm 下载完成');
        generateMocks();
      });
    }).on('error', (err) => {
      fs.unlink(wasmPath, () => {}); // 删除不完整的文件
      console.error('下载过程中出错:', err.message);
    });
  } catch (error) {
    console.error('下载 tree-sitter-c.wasm 时出错:', error);
  }
}

// 主函数
async function main() {
  console.log('开始生成C项目的mock文件...');
  
  // 首先确保有tree-sitter-c.wasm文件
  await downloadTreeSitterWasm();
}

// 执行主函数
main().catch(console.error);